﻿using System.Collections.Generic;
using System.Linq;
using log4net;
using System.Text;
using TdxApiPool.Invoker;

namespace TdxApiPool.Connect
{
    public class ConnectPool
    {
        private static readonly ILog Log = LogManager.GetLogger("ConnectPool");

        public readonly List<TdxConnection> Connections = new List<TdxConnection>();
        public readonly List<TdxConnection> FunConnections = new List<TdxConnection>();

        private static readonly ConnectPool Instance = new ConnectPool();

        public static ConnectPool GetInstance()
        {
            return Instance;
        }

        private ConnectPool()
        {
            StringBuilder result = new StringBuilder(1024 * 1024);
            StringBuilder errInfo = new StringBuilder(256);

            Dictionary<string, DllInvoker> invokers = DllManager.Instance.Invokers;
            Dictionary<string, int> baseMarketHost = Config.GetConfig()
                .BaseMarket.Host.ToDictionary(m => m.IpAddress, m => m.Port);
            foreach (var pair in invokers)
            {
                var key = pair.Key;
                var ip = key.Split('_')[0];
                result.Clear();
                errInfo.Clear();
                DllInvoker dllInvoker = pair.Value;
                int port;
                bool tryGetValue = baseMarketHost.TryGetValue(ip, out port);
                bool success = tryGetValue;

                if (!success)
                {
                    continue;
                }

                QuoteDelegate.TdxHq_Connect connectDelegate =
                    (QuoteDelegate.TdxHq_Connect)
                    dllInvoker.Invoke("TdxHq_Connect", typeof(QuoteDelegate.TdxHq_Connect));
                long firstTicks = System.DateTime.Now.Ticks;
                bool connected = connectDelegate(ip, port, result, errInfo);
                long secondTicks = System.DateTime.Now.Ticks;
                long delay = secondTicks - firstTicks;
                string connectionName = "";

                Log.Info("ip:" + ip);
                Log.Info("result:" + result);
                Log.Info("delay:" + delay / 100 + "ms");

                if (!connected)
                {
                    Log.Error("errInfo:" + errInfo);
                    Log.Error("放弃连接服务器:" + ip);
                    Log.Error("======================");
                    continue;
                }

                var strings = result.ToString().Split('\t')[2].Split('\n');
                connectionName = strings[1];

                Log.Error("======================");

                TdxConnection tdxConnection = new TdxConnection(ip, port, pair.Value)
                {
                    ConnectionName = connectionName,
                    Connected = true,
                    Delay = delay
                };
                if (key.Contains("query"))
                {
                    FunConnections.Add(tdxConnection);
                    tdxConnection.ConnectionTag = "query";
                }
                else if (key.Contains("faster"))
                {
                    Connections.Add(tdxConnection);
                    tdxConnection.ConnectionTag = "faster";
                }
                else
                {
                    Connections.Add(tdxConnection);
                    tdxConnection.ConnectionTag = "base";
                }
            }
        }

        public TdxConnection GetFunConnection()
        {
            return FunConnections.OrderBy(m => m.Delay).First();
        }

        public TdxConnection GetFasterConncetions()
        {
            return Connections.Where(m => m.Connected).OrderBy(m => m.Delay).First();
        }

        public List<TdxConnection> GetAvailabeConncetions()
        {
            return Connections.Where(m => m.Connected).ToList();
        }

        public List<TdxConnection> GetUnAvailabeConnections()
        {
            return Connections.Where(m => !m.Connected).ToList();
        }
    }
}